package org.inspiration.dudu.common.config;


import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.RequiredArgsConstructor;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;


@Configuration

public class RabbitMQConfig {

    @Value("${dudu.rabbitmq.exchanges.like-exchange.type}")
    private String likeExchangeType;

    @Value("${dudu.rabbitmq.exchanges.like-exchange.queues.user-like-queue.name}")
    private String userLikeQueueName;
    @Value("${dudu.rabbitmq.exchanges.like-exchange.queues.user-like-queue.routing-key}")
    private String userLikeRoutingKey;


    @Value("${dudu.rabbitmq.exchanges.like-exchange.queues.article-like-queue.name}")
    private String articleLikeQueueName;
    @Value("${dudu.rabbitmq.exchanges.like-exchange.queues.article-like-queue.routing-key}")
    private String articleLikeRoutingKey;



    @Value("${dudu.rabbitmq.exchanges.like-exchange.queues.question-like-queue.name}")
    private String questionLikeQueueName;
    @Value("${dudu.rabbitmq.exchanges.like-exchange.queues.question-like-queue.routing-key}")
    private String questionLikeRoutingKey;



    @Value("${dudu.rabbitmq.exchanges.like-exchange.queues.answer-like-queue.name}")
    private String answerLikeQueueName;
    @Value("${dudu.rabbitmq.exchanges.like-exchange.queues.answer-like-queue.routing-key}")
    private String answerLikeRoutingKey;



    @Value("${dudu.rabbitmq.exchanges.like-exchange.queues.comment-like-queue.name}")
    private String commentLikeQueueName;
    @Value("${dudu.rabbitmq.exchanges.like-exchange.queues.comment-like-queue.routing-key}")
    private String commentLikeRoutingKey;


    @Bean
    public MessageConverter jsonMessageConverter() {
        // 设置objectMapper:转换java对象的时候使用
        ObjectMapper objectMapper = new ObjectMapper();

        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);

        // 将日期序列化为可读字符串而不是时间戳
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        //设置时间模块(格式化，不设置，则输出默认格式)
        JavaTimeModule timeModule = new JavaTimeModule();
        // LocalDateTime
        timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.of("Asia/Shanghai"))));
        timeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.of("Asia/Shanghai"))));
        // LocalDate
        timeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneId.of("Asia/Shanghai"))));
        timeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneId.of("Asia/Shanghai"))));

        // 设置自定义时间模块
        objectMapper.registerModule(timeModule);
        return new Jackson2JsonMessageConverter(objectMapper);
    }
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        rabbitTemplate.setMessageConverter(jsonMessageConverter());
        return rabbitTemplate;
    }

    @Bean
    public Exchange likeExchange() {
        return switch (likeExchangeType) {
            case "direct" -> new DirectExchange("like-exchange");
            case "topic" -> new TopicExchange("like-exchange");
            case "fanout" -> new FanoutExchange("like-exchange");
            case "headers" -> new HeadersExchange("like-exchange");
            default -> throw new IllegalArgumentException("Unsupported exchange type: " + likeExchangeType);
        };
    }

    @Bean
    public Queue userLikeQueue() {
        return new Queue(userLikeQueueName, true);
    }



    @Bean
    public Queue articleLikeQueue() {
        return new Queue(articleLikeQueueName, true);
    }



    @Bean
    public Queue questionLikeQueue() {
        return new Queue(questionLikeQueueName, true);
    }



    @Bean
    public Queue answerLikeQueue() {
        return new Queue(answerLikeQueueName, true);
    }



    @Bean
    public Queue commentLikeQueue() {
        return new Queue(commentLikeQueueName, true);
    }



    @Bean
    public Binding userLikeBinding(Exchange likeExchange, Queue userLikeQueue) {
        return BindingBuilder.bind(userLikeQueue).to(likeExchange).with(userLikeRoutingKey).noargs();
    }



    @Bean
    public Binding articleLikeBinding(Exchange likeExchange, Queue articleLikeQueue) {
        return BindingBuilder.bind(articleLikeQueue).to(likeExchange).with(articleLikeRoutingKey).noargs();
    }



    @Bean
    public Binding questionLikeBinding(Exchange likeExchange, Queue questionLikeQueue) {
        return BindingBuilder.bind(questionLikeQueue).to(likeExchange).with(questionLikeRoutingKey).noargs();
    }



    @Bean
    public Binding answerLikeBinding(Exchange likeExchange, Queue answerLikeQueue) {
        return BindingBuilder.bind(answerLikeQueue).to(likeExchange).with(answerLikeRoutingKey).noargs();
    }



    @Bean
    public Binding commentLikeBinding(Exchange likeExchange, Queue commentLikeQueue) {
        return BindingBuilder.bind(commentLikeQueue).to(likeExchange).with(commentLikeRoutingKey).noargs();
    }


}